package com.ruoyi.activiti.controller;

import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ruoyi.activiti.domain.dto.ModelDesignDto;
import com.ruoyi.activiti.domain.dto.ModelDto;
import com.ruoyi.activiti.domain.dto.ModelQueryDto;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.StringUtils;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ModelQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;


@RestController
@RequestMapping("/model/manage")
public class ModelManagerController extends BaseController {

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 查询模型列表
     * */
    @GetMapping("/modelLists")
    public TableDataInfo modelLists(ModelQueryDto modelQueryDto) {
        ModelQuery query = repositoryService.createModelQuery();
        if (StringUtils.isNotEmpty(modelQueryDto.getKey())) {
            query.modelKey(modelQueryDto.getKey());
        }
        if (StringUtils.isNotEmpty(modelQueryDto.getName())) {
            query.modelNameLike("%"+modelQueryDto.getName()+"%");
        }
        int start = (modelQueryDto.getPageNum() - 1) * modelQueryDto.getPageSize();
        List<Model> page = query.orderByCreateTime().desc().listPage(start, modelQueryDto.getPageSize());
        int total = repositoryService.createModelQuery().list().size();
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setRows(page);
        rspData.setTotal(total);
        return rspData;
    }

    /**
     * 保存模型
     * */
    @PostMapping("/add")
    public AjaxResult addSave(@RequestBody ModelDto modelDto) throws JsonProcessingException {
        modelDto.setVersion(1);
        Model model = repositoryService.newModel();
        model.setCategory(modelDto.getCategory());
        model.setKey(modelDto.getKey());
        ObjectNode modelNode = objectMapper.createObjectNode();
        modelNode.put("name", modelDto.getName());
        modelNode.put("description", modelDto.getDescription());
        modelNode.put("revision", modelDto.getVersion());
        model.setMetaInfo(modelNode.toString());
        model.setName(modelDto.getName());
        model.setVersion(modelDto.getVersion());
        ModelQuery modelQuery = repositoryService.createModelQuery();
        List<Model> list = modelQuery.modelKey(modelDto.getKey()).list();
        if (!list.isEmpty()) {
            return AjaxResult.error("模型标识不能重复");
        } else {
            // 保存模型到act_re_model表
            repositoryService.saveModel(model);
//            HashMap<String, Object> content = new HashMap();
//            content.put("resourceId", model.getId());
//            HashMap<String, String> properties = new HashMap();
//            properties.put("process_id", modelDto.getKey());
//            properties.put("name", modelDto.getName());
//            properties.put("category", modelDto.getCategory());
//            content.put("properties", properties);
//            HashMap<String, String> stencilset = new HashMap();
//            stencilset.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
//            content.put("stencilset", stencilset);
//            // 保存模型文件到act_ge_bytearray表
//            repositoryService.addModelEditorSource(model.getId(), objectMapper.writeValueAsBytes(content));
            return AjaxResult.success(model);
        }
    }

    /**
     * 编辑流程设计
     * @param modelId 模型id
     * */
    @GetMapping("/{modelId}")
    public AjaxResult getEditorJson(@PathVariable("modelId") String modelId) throws Exception {
        HashMap<String, Object> hm = new HashMap<>();
        Model model = repositoryService.getModel(modelId);
        JSONObject jsonObject = JSONObject.parse(model.getMetaInfo());
        hm.put("name", model.getName());
        hm.put("category", model.getCategory());
        hm.put("version", model.getVersion());
        hm.put("key", model.getKey());
        hm.put("modelId", model.getId());
        hm.put("description", jsonObject.getString("description"));
        byte[] modelEditorSources = repositoryService.getModelEditorSource(model.getId());
        String bpmnXml = "";
        if (modelEditorSources != null && modelEditorSources.length > 0) {
            bpmnXml = new String(modelEditorSources, "utf-8");
        }
        hm.put("bpmnXml", bpmnXml);
        return AjaxResult.success(hm);
    }

    /**
     * 保存流程设计
     * */
    @PutMapping("/save/design")
    public AjaxResult saveModel(@RequestBody ModelDesignDto modelDesignDto) {
        try {
            Model model = repositoryService.getModel(modelDesignDto.getModelId());
            ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
            modelJson.put("name", modelDesignDto.getName());
            modelJson.put("description", modelDesignDto.getDescription());
            model.setMetaInfo(modelJson.toString());
            model.setName(modelDesignDto.getName());
            model.setDeploymentId(null);
            Integer version = model.getVersion();
            version++;
            model.setVersion(version);
            repositoryService.saveModel(model);
            repositoryService.addModelEditorSource(model.getId(), modelDesignDto.getBmnXml().getBytes("utf-8"));
        } catch (Exception e) {
            logger.error("Error saving model", e);
            throw new ActivitiException("Error saving model", e);
        }
        return AjaxResult.success();
    }

    /**
     * 删除模型
     * @param modelId 模型id
     * */
    @DeleteMapping("/{modelId}")
    public AjaxResult deleteModel(@PathVariable("modelId") String modelId) {
        repositoryService.deleteModel(modelId);
        return AjaxResult.success("模型删除成功");
    }

    /**
    * 部署模型
     * @param modelId 模型id
    * */
    @PostMapping("/deploy")
    public AjaxResult deploy(@RequestParam("modelId") String modelId) throws Exception {
        // 根据id查询模型
        Model model = repositoryService.getModel(modelId);
        // 查出存储的流程图
        byte[] modelEditorSource = repositoryService.getModelEditorSource(model.getId());
        if(modelEditorSource != null && modelEditorSource.length > 0) {
            String bpmnXml = new String(modelEditorSource,"utf-8");
            logger.info(bpmnXml);
            // 部署流程
            repositoryService.createDeployment()
                    .name(model.getName())
                    .addString(model.getName() + ".bpmn20.xml", bpmnXml)
                    .key(model.getKey())
                    .category(model.getCategory())
                    .deploy();
        } else {
            return AjaxResult.error("请先设计流程");
        }
        return AjaxResult.success("部署成功");
    }
}
